<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>你不知道的JavaScript(上) | 20秒的勇气</title>
    <meta name="generator" content="VuePress 1.5.3">
    <script>var _hmt = _hmt || [];
      (function() {
        var hm = document.createElement("script");
        hm.src = "https://hm.baidu.com/hm.js?01611e9c2d4c65531fe791d0a83e6ebd";
        var s = document.getElementsByTagName("script")[0]; 
        s.parentNode.insertBefore(hm, s);
      })()</script>
    <meta name="description" content="欢迎来到wenbintian的博客">
    <link rel="preload" href="/blog/assets/css/0.styles.5dc057b1.css" as="style"><link rel="preload" href="/blog/assets/js/app.2a047d56.js" as="script"><link rel="preload" href="/blog/assets/js/2.cc145974.js" as="script"><link rel="preload" href="/blog/assets/js/8.902b76dc.js" as="script"><link rel="prefetch" href="/blog/assets/js/10.dc9f6a74.js"><link rel="prefetch" href="/blog/assets/js/11.f7ecaf96.js"><link rel="prefetch" href="/blog/assets/js/12.4363725a.js"><link rel="prefetch" href="/blog/assets/js/13.0fd4b251.js"><link rel="prefetch" href="/blog/assets/js/14.edc7bd5f.js"><link rel="prefetch" href="/blog/assets/js/15.647c0964.js"><link rel="prefetch" href="/blog/assets/js/16.2e8857c5.js"><link rel="prefetch" href="/blog/assets/js/17.1c7cc9ee.js"><link rel="prefetch" href="/blog/assets/js/18.bf88a22d.js"><link rel="prefetch" href="/blog/assets/js/19.1433c5a8.js"><link rel="prefetch" href="/blog/assets/js/20.713720d3.js"><link rel="prefetch" href="/blog/assets/js/21.51a3d47b.js"><link rel="prefetch" href="/blog/assets/js/22.04488762.js"><link rel="prefetch" href="/blog/assets/js/23.b9337410.js"><link rel="prefetch" href="/blog/assets/js/24.d0d5b562.js"><link rel="prefetch" href="/blog/assets/js/25.e76a54ef.js"><link rel="prefetch" href="/blog/assets/js/26.006d0afa.js"><link rel="prefetch" href="/blog/assets/js/27.38ec3468.js"><link rel="prefetch" href="/blog/assets/js/28.c8cf7077.js"><link rel="prefetch" href="/blog/assets/js/29.70f03487.js"><link rel="prefetch" href="/blog/assets/js/3.9bfe5560.js"><link rel="prefetch" href="/blog/assets/js/30.3e6d6ba9.js"><link rel="prefetch" href="/blog/assets/js/31.1dbd85cb.js"><link rel="prefetch" href="/blog/assets/js/32.208e4272.js"><link rel="prefetch" href="/blog/assets/js/33.979228dd.js"><link rel="prefetch" href="/blog/assets/js/34.6ad6fae2.js"><link rel="prefetch" href="/blog/assets/js/35.59b3e591.js"><link rel="prefetch" href="/blog/assets/js/36.7239d917.js"><link rel="prefetch" href="/blog/assets/js/37.a8305f70.js"><link rel="prefetch" href="/blog/assets/js/38.7e3197cd.js"><link rel="prefetch" href="/blog/assets/js/39.1bb3ad3b.js"><link rel="prefetch" href="/blog/assets/js/4.3b6a7e49.js"><link rel="prefetch" href="/blog/assets/js/40.bc263e99.js"><link rel="prefetch" href="/blog/assets/js/41.4ee25f6a.js"><link rel="prefetch" href="/blog/assets/js/42.37c6cc26.js"><link rel="prefetch" href="/blog/assets/js/43.9a40d780.js"><link rel="prefetch" href="/blog/assets/js/44.2eda0bb6.js"><link rel="prefetch" href="/blog/assets/js/45.ce3372d9.js"><link rel="prefetch" href="/blog/assets/js/46.17e44796.js"><link rel="prefetch" href="/blog/assets/js/47.f845ed6d.js"><link rel="prefetch" href="/blog/assets/js/5.bc6e1aa4.js"><link rel="prefetch" href="/blog/assets/js/6.e0f80af7.js"><link rel="prefetch" href="/blog/assets/js/7.c808e2d2.js"><link rel="prefetch" href="/blog/assets/js/9.9bb8a7fe.js">
    <link rel="stylesheet" href="/blog/assets/css/0.styles.5dc057b1.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/blog/" class="home-link router-link-active"><!----> <span class="site-name">20秒的勇气</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/blog/knowledge/" class="nav-link router-link-active">
  知识篇
</a></div><div class="nav-item"><a href="/blog/notes/" class="nav-link">
  随身笔记
</a></div> <a href="https://github.com/wenbintian" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/blog/knowledge/" class="nav-link router-link-active">
  知识篇
</a></div><div class="nav-item"><a href="/blog/notes/" class="nav-link">
  随身笔记
</a></div> <a href="https://github.com/wenbintian" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav>  <ul class="sidebar-links"><li><section class="sidebar-group collapsable depth-0"><a href="/blog/knowledge/book/" class="sidebar-heading clickable router-link-active open"><span>读书篇</span> <span class="arrow down"></span></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/blog/knowledge/book/knowjs1.html" aria-current="page" class="active sidebar-link">你不知道的JavaScript(上)</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/blog/knowledge/book/knowjs1.html#第二部分-this-和对象原型" class="sidebar-link">第二部分 this 和对象原型</a></li></ul></li><li><a href="/blog/knowledge/book/knowjs2.html" class="sidebar-link">你不知道的JavaScript(中)</a></li><li><a href="/blog/knowledge/book/knowjs3.html" class="sidebar-link">你不知道的JavaScript(下)</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><a href="/blog/knowledge/tool/" class="sidebar-heading clickable"><span>工具篇</span> <span class="arrow right"></span></a> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><a href="/blog/knowledge/css/" class="sidebar-heading clickable"><span>CSS篇</span> <span class="arrow right"></span></a> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><a href="/blog/knowledge/js/" class="sidebar-heading clickable"><span>JS篇</span> <span class="arrow right"></span></a> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="你不知道的javascript-上"><a href="#你不知道的javascript-上" class="header-anchor">#</a> 你不知道的JavaScript(上)</h1> <h2 id="第二部分-this-和对象原型"><a href="#第二部分-this-和对象原型" class="header-anchor">#</a> 第二部分 this 和对象原型</h2> <p>任何足够先进的技术都与魔法无异。
---Arthur.C Clarke</p> <h3 id="第1章-关于this"><a href="#第1章-关于this" class="header-anchor">#</a> 第1章 关于this</h3> <h4 id="_1-this到底是什么"><a href="#_1-this到底是什么" class="header-anchor">#</a> 1.this到底是什么</h4> <div class="language- extra-class"><pre><code>this是**在运行时**进行绑定的，并不是在编写时绑定的，它的上下文取决于行数调用时的各种条件。
this的绑定和函数声明的位置没有任何关系，只取决于函数的调用方式。
this实际上是在函数被调用时发生的绑定，它指向什么完全取决于函数在哪里被调用。
</code></pre></div><p><img src="https://img-blog.csdnimg.cn/20200808171156985.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDY1MzMyOQ==,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"> <img src="https://img-blog.csdnimg.cn/20200808171242769.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDY1MzMyOQ==,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p> <h3 id="第2章-this全面解析"><a href="#第2章-this全面解析" class="header-anchor">#</a> 第2章 this全面解析</h3> <h4 id="_1-如何判断this"><a href="#_1-如何判断this" class="header-anchor">#</a> 1.如何判断this</h4> <div class="language- extra-class"><pre><code>可以从以下方面进行判断：
</code></pre></div><ol><li>函数是否在<code>new</code>中调用（<code>new</code>绑定）？如果是的话<code>this</code>绑定的是新创建的对象。<code>var bar = new foo()</code></li> <li>函数是否通过<code>call、apply</code>(显示绑定)或者硬绑定调用？如果是的话，<code>this</code>绑定的是指定的对象。<code>var bar = foo.call(obj2)</code></li> <li>函数是否在某个上下文对象中调用（隐式绑定）？如果是的话，<code>this</code>绑定的是哪个上下文对象。<code>var bar = obj1.foo()</code></li> <li>如果都不是的话，使用默认绑定。如果再严格模式下，就绑定到<code>undefined</code>，否则绑定到全局对象。<code>var bar = foo()</code></li></ol> <p><img src="https://img-blog.csdnimg.cn/20200808171354367.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDY1MzMyOQ==,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p> <h4 id="_2-被忽略的this"><a href="#_2-被忽略的this" class="header-anchor">#</a> 2. 被忽略的this</h4> <p>如果你把<code>null</code>或者<code>undefined</code>作为<code>this</code>的绑定对象传入<code>call、apply</code>或者<code>bind</code>，这些值在调用时会被忽略，实际应用的是默认绑定规则：</p> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">function</span> <span class="token function">foo</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>a<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token number">2</span>
<span class="token function">foo</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token comment">// 2</span>
</code></pre></div><div class="language- extra-class"><pre><code>那么什么情况下会传入null呢？
</code></pre></div><p>一种是非常常见的做法是使用<code>apply(..)</code>来“展开”一个数组，并当作参数传入一个函数。另一种是<code>bind(..)</code>可以对参数 进行柯里化（预先设置一些参数）：</p> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">function</span> <span class="token function">foo</span><span class="token punctuation">(</span><span class="token parameter">a<span class="token punctuation">,</span>b</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'a:'</span> <span class="token operator">+</span> a<span class="token punctuation">,</span> <span class="token string">'b:'</span> <span class="token operator">+</span> b<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token comment">// 把数组“展开”成参数</span>
<span class="token function">foo</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token comment">// a:2 b:3</span>

<span class="token comment">//使用bind(..)进行柯里化</span>
<span class="token keyword">var</span> bar <span class="token operator">=</span> <span class="token function">foo</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span>
<span class="token function">bar</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span> <span class="token comment">// a:2 b:3</span>
</code></pre></div><p>这两种方法都需要传入一个参数当作<code>this</code>的绑定对象。如果不关心<code>this</code>的话，你仍然需要传入一个占位符，这时<code>null</code>可能是一个不错的选择，如上。
<img src="https://img-blog.csdnimg.cn/20200808171628987.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDY1MzMyOQ==,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p> <h4 id="_3-更安全的this"><a href="#_3-更安全的this" class="header-anchor">#</a> 3. 更安全的this</h4> <p>在  <code>JavaScript</code>中创建一个空对象最简单的方法是<code>Object.create(null)</code>。<code>Object.create(null)</code>和<code>{}</code>很像，但是并不会创建<code>Object.prototype</code>这个委托，所以它比<code>{}</code>“更空”。
<img src="https://img-blog.csdnimg.cn/20200808171718278.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDY1MzMyOQ==,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p> <p>赋值表达式 <code>p.foo = o.foo</code>的返回值是目标函数的引用，因此调用对象的位置是<code>foo()</code>而不是<code>p.foo()</code>或者<code>o.foo()</code>。使用的是默认绑定规则。</p> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">function</span> <span class="token function">foo</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>a<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token number">2</span>
<span class="token keyword">var</span> o <span class="token operator">=</span> <span class="token punctuation">{</span> a<span class="token operator">:</span> <span class="token number">3</span><span class="token punctuation">,</span> foo<span class="token operator">:</span> foo <span class="token punctuation">}</span>
<span class="token keyword">var</span> p <span class="token operator">=</span> <span class="token punctuation">{</span> a<span class="token operator">:</span> <span class="token number">4</span> <span class="token punctuation">}</span>
o<span class="token punctuation">.</span><span class="token function">foo</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 3</span>
<span class="token punctuation">(</span>p<span class="token punctuation">.</span>foo <span class="token operator">=</span> o<span class="token punctuation">.</span>foo<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 2</span>
</code></pre></div><p><img src="https://img-blog.csdnimg.cn/20200808171844230.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDY1MzMyOQ==,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p> <h3 id="第3章-对象"><a href="#第3章-对象" class="header-anchor">#</a> 第3章 对象</h3> <h4 id="_3-1-语法"><a href="#_3-1-语法" class="header-anchor">#</a> 3.1 语法</h4> <p>对象定义：<strong>声明（文字）形式和构造形式</strong>。</p> <ol><li>文字形式</li></ol> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">var</span> myObj <span class="token operator">=</span> <span class="token punctuation">{</span>
	key<span class="token operator">:</span> value
	<span class="token comment">//...</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre></div><ol start="2"><li>构造形式</li></ol> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">var</span> myObj <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Object</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
myObj<span class="token punctuation">.</span>key <span class="token operator">=</span> value<span class="token punctuation">;</span>
</code></pre></div><p>区别：
二者产生的对象是一样的。唯一区别是文字形式可以一次性添加多个属性，而构造形式只能逐个添加属性。</p> <h4 id="_3-2-类型"><a href="#_3-2-类型" class="header-anchor">#</a> 3.2 类型</h4> <ul><li>基本类型： <code>String</code>、<code>Number</code>、<code>Boolean</code>、<code>Undefined</code>、<code>Null</code>、<code>Symbol</code></li> <li>引用数据类型：<code>Object</code>
==注：Symbol 是 ES6 引入了一种新的原始数据类型，表示独一无二的值。==
注：有一种错误的说法。&quot;JavaScript 中万物皆是对象&quot;，这显然是不对的，因为基本类型本身并不是对象。对于<code>typeof null</code> 会返回<code>object</code>，那是语言本事的一个bug，二进制前三位都是<code>0</code>的话会被判为<code>object</code>类型，而<code>null</code>的二进制是32个<code>0</code>，所以类型是<code>object</code>.</li></ul> <h5 id="内置对象"><a href="#内置对象" class="header-anchor">#</a> 内置对象</h5> <p>JavaScript中有一些<strong>对象子类型</strong>，通常被称为<strong>内置对象</strong>。</p> <ul><li><code>String</code></li> <li><code>Number</code></li> <li><code>Boolean</code></li> <li><code>Object</code></li> <li><code>Function</code></li> <li><code>Array</code></li> <li><code>Date</code></li> <li><code>RegExp</code></li> <li><code>Error</code>
在JavaScript中它们实际上是一些内置函数。可以被当做构造函数来使用（由<code>new</code>产生的函数调用）。</li></ul> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">var</span> str <span class="token operator">=</span> <span class="token string">'I am a string'</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> strObject <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span>str<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">typeof</span> strObject<span class="token punctuation">;</span> <span class="token comment">// &quot;Object&quot;</span>
strObject <span class="token keyword">instanceof</span> <span class="token class-name">String</span><span class="token punctuation">;</span> <span class="token comment">// true</span>
</code></pre></div><p><strong>通过以下方法可以检查对象子类型</strong></p> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token class-name">Object</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// [object, Date]</span>
<span class="token class-name">Object</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// [object, Object]</span>
<span class="token class-name">Object</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// [object, Number]</span>
</code></pre></div><h4 id="_3-3-内容"><a href="#_3-3-内容" class="header-anchor">#</a> 3.3 内容</h4> <ul><li>在对象中，属性名永远都是字符串。</li> <li>若不是字符串，则首先会先被转换成字符串。</li></ul> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">var</span> myObject <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
myObject<span class="token punctuation">[</span><span class="token boolean">true</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">'foo'</span><span class="token punctuation">;</span>
myObject<span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">'bar'</span><span class="token punctuation">;</span>
myObject<span class="token punctuation">[</span>myObject<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">'baz'</span><span class="token punctuation">;</span>

myObject<span class="token punctuation">[</span><span class="token string">'true'</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// 'foo'</span>
myObject<span class="token punctuation">[</span><span class="token string">'3'</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// 'bar'</span>
<span class="token comment">// 对象转成字符串是 '[object, Object]'</span>
myObject<span class="token punctuation">[</span><span class="token string">'[object Object]'</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// 'baz'</span>
</code></pre></div><h5 id="_3-3-3-数组"><a href="#_3-3-3-数组" class="header-anchor">#</a> 3.3.3 数组</h5> <p>数组也是对象，可以给数组添加属性。添加属性<code>length</code>的值不会变。</p> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">var</span> myArr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'foo'</span><span class="token punctuation">,</span> <span class="token string">'bar'</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
myArr<span class="token punctuation">.</span>zzz <span class="token operator">=</span> <span class="token string">'zzz'</span><span class="token punctuation">;</span>
myArr<span class="token punctuation">.</span>length<span class="token punctuation">;</span> <span class="token comment">// 2</span>
myArr<span class="token punctuation">.</span>zzz<span class="token punctuation">;</span> <span class="token comment">// 'zzz'</span>
</code></pre></div><p>注意：如属性名“看起来”想一个数字，那它会变成一个下标，此时就不是添加一个属性了。</p> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">var</span> myArr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'foo'</span><span class="token punctuation">,</span> <span class="token string">'bar'</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
myArr<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// 'bar'</span>
myArr<span class="token punctuation">[</span><span class="token string">'1'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">'change'</span><span class="token punctuation">;</span>
myArr<span class="token punctuation">[</span><span class="token string">'2'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">'add'</span><span class="token punctuation">;</span>
myArr<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// 'change'</span>
myArr<span class="token punctuation">.</span>length<span class="token punctuation">;</span> <span class="token comment">// 3</span>
</code></pre></div><h5 id="_3-3-5-属性描述符"><a href="#_3-3-5-属性描述符" class="header-anchor">#</a> 3.3.5 属性描述符</h5> <p>从<code>ES5</code>开始，所有属性都具备了属性描述符。</p> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">var</span> myObj <span class="token operator">=</span> <span class="token punctuation">{</span> a<span class="token operator">:</span> <span class="token number">1</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
Object<span class="token punctuation">.</span><span class="token function">getOwnPropertyDescriptor</span><span class="token punctuation">(</span>myObj<span class="token punctuation">,</span> <span class="token string">'a'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// {</span>
<span class="token comment">// 	value: 1,</span>
<span class="token comment">// 	configurable: true,</span>
<span class="token comment">// 	enumerable: true,</span>
<span class="token comment">// 	writable: true</span>
<span class="token comment">// }</span>
</code></pre></div><ul><li>通过<code>Object.getOwnPropertyDescriptor</code>函数获取属性描述符。<code>configurable</code>(可配置)、<code>enumerate</code>（可枚举）、<code>writable</code>(可写)。</li> <li>可通过<code>Object.defineProperty</code>函数去配置这些属性</li></ul> <ol><li><p><code>writable</code> 决定是否可以修改属性的值。
<em>可以把<code>writable:false</code>看成敌营了一个空的操作<code>setter</code>，<code>setter</code>被调用时抛出一个<code>TypeError</code>错误。</em></p></li> <li><p><code>configurable</code> 决定是否可以用<code>defineProperty(..)</code>方法修改属性描述符。</p> <ul><li>把<code>configurable</code>设置成<code>false</code>,是单向操作，无法撤销的。</li> <li><em><code>configurable为flase</code>时，还是可以把<code>writable</code>从<code>true</code>设置为<code>false</code>，但是无法从<code>false</code>改为<code>true</code></em>。</li> <li>除了禁止修改属性，也禁止<code>delete</code>删除属性。</li></ul></li> <li><p><code>enumerate</code>，设置<code>false</code>,则不会出现再<code>for..in</code>循环里。</p></li></ol> <h5 id="_3-3-6-不变性"><a href="#_3-3-6-不变性" class="header-anchor">#</a> 3.3.6 不变性</h5> <ol><li>对象常量
结合<code>writable:false</code>和<code>configurable:false</code>创建一个常量（不可修改、重定义和删除）。</li> <li>禁止扩展
禁止添加新的属性并且保留已有属性，可以使用<code>Object.preventExtensions( myObj )</code></li> <li>密封
<strong>禁止添加新的属性、不能重新配置、不能删除任何现有属性，但是能修改属性</strong>。可以使用<code>Object.seal</code>,实际上它对现有的对象调用<code>Object.preventExtensions( myObj )</code>，并且对每个属性设置<code>configurable：false</code>。</li> <li>冻结
<strong>禁止添加新的属性、不能重新配置、不能删除任何现有属性、不能修改属性</strong>。可以使用<code>Object.freeze</code>,实际上它对现有的对象调用<code>Object.seal( myObj )</code>，并且对每个属性设置<code>writable：false</code>。</li></ol> <h5 id="_3-3-7-get-操作"><a href="#_3-3-7-get-操作" class="header-anchor">#</a> 3.3.7 [[Get]] 操作</h5> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">var</span> myObj <span class="token operator">=</span> <span class="token punctuation">{</span>
	w<span class="token operator">:</span> <span class="token number">1</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
myObj<span class="token punctuation">.</span>w<span class="token punctuation">;</span> <span class="token comment">// 1</span>
</code></pre></div><ul><li><code>myObj</code>对象访问属性<code>w</code>，实际上是实现了<code>[[Get]]</code>操作，首先在对象中找相同的属性，没找到的话回去<code>[[Prototype]]</code>链上找，找不到返回<code>undefined</code>。</li> <li>跟普通的访问变量不同，访问变量的话找不到没有定义的是会抛出一个<code>ReferenceError</code>异常。</li></ul> <h5 id="_3-3-10-存在性"><a href="#_3-3-10-存在性" class="header-anchor">#</a> 3.3.10 存在性</h5> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">var</span> myObj <span class="token operator">=</span> <span class="token punctuation">{</span>
	w<span class="token operator">:</span> <span class="token number">2</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token class-name">Object</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span>test <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token string">'w'</span> <span class="token keyword">in</span> myObj<span class="token punctuation">;</span> <span class="token comment">// true</span>
myObj<span class="token punctuation">.</span><span class="token function">hasOwnProperty</span><span class="token punctuation">(</span><span class="token string">'w'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true</span>

<span class="token string">'test'</span> <span class="token keyword">in</span> myObj<span class="token punctuation">;</span> <span class="token comment">// true</span>
myObj<span class="token punctuation">.</span><span class="token function">hasOwnProperty</span><span class="token punctuation">(</span><span class="token string">'test'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// false</span>
</code></pre></div><ul><li><code>in</code>操作符会检查属性是否在对象及其<code>[[Prototype]]</code>原型链中，</li> <li>而<code>hasOwnProperty</code>方法只会检查属性是否在对象中。</li></ul> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">var</span> myObj <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
Object<span class="token punctuation">.</span><span class="token function">defineProperty</span><span class="token punctuation">(</span>myObj<span class="token punctuation">,</span> <span class="token string">'a'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
	enumerable<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token comment">// a 可枚举的</span>
	value<span class="token operator">:</span> <span class="token number">2</span> <span class="token comment">// 值</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
Object<span class="token punctuation">.</span><span class="token function">defineProperty</span><span class="token punctuation">(</span>myObj<span class="token punctuation">,</span> <span class="token string">'b'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
	enumerable<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token comment">// b 不可枚举的</span>
	value<span class="token operator">:</span> <span class="token number">1</span> <span class="token comment">// 值</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

myObj<span class="token punctuation">.</span><span class="token function">hasOwnProperty</span><span class="token punctuation">(</span><span class="token string">'a'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true</span>
myObj<span class="token punctuation">.</span><span class="token function">hasOwnProperty</span><span class="token punctuation">(</span><span class="token string">'b'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true</span>
<span class="token string">'a'</span> <span class="token keyword">in</span> myObj<span class="token punctuation">;</span> <span class="token comment">// true</span>
<span class="token string">'b'</span> <span class="token keyword">in</span> myObj<span class="token punctuation">;</span> <span class="token comment">// true</span>
<span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">var</span> key <span class="token keyword">in</span> myObj<span class="token punctuation">)</span> <span class="token punctuation">{</span>
	console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>key<span class="token punctuation">,</span> myObj<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token comment">// a 2</span>

myObj<span class="token punctuation">.</span><span class="token function">propertyIsEnumerable</span><span class="token punctuation">(</span><span class="token string">'a'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true</span>
myObj<span class="token punctuation">.</span><span class="token function">propertyIsEnumerable</span><span class="token punctuation">(</span><span class="token string">'b'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// false</span>

Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>myObj<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// ['a']</span>
Object<span class="token punctuation">.</span><span class="token function">getOwnPrepertyNames</span><span class="token punctuation">(</span>myObj<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// ['a', 'b']</span>
</code></pre></div><ul><li>可以看到<code>enumerate：false</code>,还是可以用<code>hasOwnProperty</code>和<code>in</code>操作符判断是否存在，但是在<code>for..in</code>遍历中显示不出来，<code>可枚举</code>相当于<code>可以出现在对象属性的遍历中</code>。</li> <li><code>propertyIsEnumerable</code>会检查属性名是否直接在对象上（不会检查<code>[[Prototype]]</code>原型链）并且满足<code>enumerate:true</code>。</li> <li><code>Object.keys(myObj)</code>，返回所有可枚举的属性（不查找<code>[[Property]]</code>原型链）。</li> <li><code>Object.getOwnPrepertyNames(myObj)</code>，返回所有属性，不管是否可枚举（不查找<code>[[Property]]</code>原型链）。</li></ul></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">最后一次修改时间:</span> <span class="time">8/20/2020, 11:12:19 PM</span></div></footer> <div class="page-nav"><p class="inner"><!----> <span class="next"><a href="/blog/knowledge/book/knowjs2.html">
        你不知道的JavaScript(中)
      </a>
      →
    </span></p></div> </main></div><div class="global-ui"></div></div>
    <script src="/blog/assets/js/app.2a047d56.js" defer></script><script src="/blog/assets/js/2.cc145974.js" defer></script><script src="/blog/assets/js/8.902b76dc.js" defer></script>
  </body>
</html>
